/**
 * Copyright (c) 2009  Collaborative Development Group, C.S. Dept., University of Bari
 *
 * All rights reserved. This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0  which accompanies this distribution, and is 
 * available at http://www.eclipse.org/legal/epl-v10.html
 */
package it.uniba.di.cdg.penelope.ui.swt;

import static org.junit.Assert.fail;
import it.uniba.di.cdg.penelope.presenterfirst.AbstractInjectedTests;

import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.matcher.Matchers;

/**
 * Verify that the {@link SWT}
 */
public class SWTThreadInterceptorIntegrationTest extends AbstractInjectedTests {

	private static Display display;
	
	public static class DisplayProvider implements Provider<Display> {
		/* (non-Javadoc)
		 * @see com.google.inject.Provider#get()
		 */
		@Override
		public Display get() {
			if (display == null) {
				display = new Display();
			}
			return display;
		}
	}

	public static class WriterThread extends Thread {
		
		public final Label target;

		public WriterThread( Label target ) {
			super();
			this.target = target;
		}

		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		@Override
		public void run() {
			changeLabelText();
		}

		@SWTAsyncExec
		public void changeLabelText() {
			target.setText( "Differente Text" );
		}
	}

	public static class ReaderThread extends Thread {
		
		public final Label target;
		private String text;

		public ReaderThread( Label target ) {
			super();
			this.target = target;
		}

		/* (non-Javadoc)
		 * @see java.lang.Thread#run()
		 */
		@Override
		public void run() {
			this.text = readLabelText();
			
		}

		@SWTSyncExec
		public String readLabelText() {
			return target.getText();
		}
	}
	
	public static class TestConfig extends AbstractModule {
		/* (non-Javadoc)
		 * @see com.google.inject.AbstractModule#configure()
		 */
		protected void configure() {
			bind( Display.class ).toProvider( DisplayProvider.class );
			
			// SWT Thread Synchronization
			SWTThreadInterceptor swtThreadingInterceptor = new SWTThreadInterceptor();
			requestInjection( swtThreadingInterceptor );
			bindInterceptor( Matchers.any(), Matchers.annotatedWith( SWTSyncExec.class ), swtThreadingInterceptor );
		}
	}

	private Shell shell;
	
	@Before
	public void startGUI() {
		shell = new Shell( display );
		
		shell.setText( "Hello, world!" );
		shell.setLayout( new FillLayout() );
		
		Label label = new Label( shell, SWT.CENTER );
		label.setText( "untouched" );
		
		shell.open();
	}

	@After
	public void stopGUI() {
		shell.close();
		display.dispose();
	}
	
	@Test
	public void shouldExecuteInTheSWTEventQueue() {
		WriterThread worker = getInstance( WriterThread.class );
		worker.start();
		
		fail( "Not implemented" );
	}

	@Test
	public void shouldAsyncExecuteInTheSWTEventQueue() {
		fail( "Not implemented" );
	}
	
	@Test( expected = SWTException.class )
	public void willNotWork() {
		fail( "Not implemented" );
	}

	/* (non-Javadoc)
	 * @see it.uniba.di.cdg.penelope.presenterfirst.AbstractInjectedTests#provideConfigs(java.util.List)
	 */
	@Override
	protected void provideConfigs( List<Module> modules ) {
		modules.add( new TestConfig() );
	}
}
